package com.corewillsoft.fireflies.gameobjects.obstacles;

import com.corewillsoft.fireflies.gameobjects.obstacles.Obstacle.ObstacleType;
import com.corewillsoft.fireflies.gameobjects.obstacles.Obstacle.ObstacleParameterType;
import com.corewillsoft.fireflies.gameobjects.obstacles.Obstacle.ObstacleParameters;
import com.corewillsoft.fireflies.gameobjects.obstacles.Obstacle.ObstacleParametersList;
import com.corewillsoft.fireflies.gameobjects.obstacles.trajectories.Trajectory;
import com.corewillsoft.fireflies.gameobjects.obstacles.trajectories.Trajectory.TrajectoryType;
import com.corewillsoft.fireflies.gameobjects.obstacles.trajectories.TrajectoryFactory;

import java.util.Map.Entry;

public class ObstacleFactory {

	public static Obstacle createObstacle(ObstacleType type) {
		return createObstacle(type, 0, 0);
	}

	public static Obstacle createObstacle(ObstacleType type, int x, int y) {
		Obstacle obstacle = null;
		switch (type) {
		case FROG:
			obstacle = new Frog(x, y);
			break;
		case HORNET:
			obstacle = new Hornet(x, y);
			break;
		case FAN:
			obstacle = new Fan(x, y);
			break;
		case WALL:
			obstacle = new Wall(x, y);
			break;
		default:
			obstacle = null;
		}
		return obstacle;
	}

	/**
	 * Creates and returns instance of obstacle by known its type and parameters
	 * @param type - type of the obstacle
	 * @param x - initial x-coordinate of the obstacle
	 * @param y - initial y-coordinate of the obstacle
	 * @param obstacleParameters - configurable parameters of the obstacle (which are kept in DB)
	 * @return created obstacle
	 */
	public static Obstacle createObstacle(ObstacleType type, int x, int y, final ObstacleParameters obstacleParameters) {
		Obstacle obstacle = createObstacle(type, x, y);

		if (obstacle != null) {
			obstacle.setParametersMap(obstacleParameters);

			//loop by all sets of different parameters of the obstacle
			for (Entry<ObstacleParameterType, ObstacleParametersList> parameterEntry: obstacleParameters.entrySet()) {
				ObstacleParameterType parameterType = parameterEntry.getKey();
				switch (parameterType) {
					case SIZE:
						/*
						required SIZE parameters in the list:
						 0 - width of obstacle
						 1 - height of obstacle
						 */
						ObstacleParametersList sizeParametersList = parameterEntry.getValue();
						if (sizeParametersList.size() == 2) {
							float obstacleWidth = sizeParametersList.get(0);
							float obstacleHeight = sizeParametersList.get(1);
							obstacle.setWidth(obstacleWidth);
							obstacle.setHeight(obstacleHeight);
						}
						break;
					case TRAJECTORY:
						/*
						required TRAJECTORY parameters in the list:
						0 - type of trajectory (ordinal value of element of TrajectoryType enumeration)
						1... - variable amount of trajectory-specific parameters (see TrajectoryFactory.createTrajectory for description of these parameter)
						 */
						ObstacleParametersList trajectoryParameters = new ObstacleParametersList();
						trajectoryParameters.addAll(parameterEntry.getValue());

						if (trajectoryParameters.size() > 0) {
							TrajectoryType trajectoryType = TrajectoryType.values()[trajectoryParameters.get(0).intValue()];
							trajectoryParameters.remove(0);		//remove trajectory type from trajectory parameters list

							//create trajectory instance by known its parameters
							Trajectory trajectory = TrajectoryFactory.createTrajectory(trajectoryType, trajectoryParameters);
							obstacle.setTrajectory(trajectory);
						}
						break;
				}
			}
		}

		return obstacle;
	}
}
